/**
 * @copyright   Kevin
 * @license     LGPL 3.0
 * @author      Kevin
 * @checkout    https://gitee.com/bigearrabbit/KevinQt.git
 * @file        KevinListModel.cpp
 */

#include <QDebug>
#include <QVector>

#include "KevinListModel.h"

namespace Kevin {
//---------------------------------
ListModel::ListModel(QObject* parent)
    : QAbstractListModel(parent)
    , m_pDataList(nullptr) {
    // qDebug() << "ListModel::ListModel()";
    m_pDataList = new QList<ListItem>();
}
//---------------------------------
ListModel::~ListModel() {
    // qDebug() << "ListModel::~ListModel()";
    delete m_pDataList;
    m_pDataList = nullptr;
}
//---------------------------------
int ListModel::append(const ListItem& data) {
    // qDebug() << "ListModel::append(" << &data << ")";
    return insert(m_pDataList->count(), data);
}
//---------------------------------
int ListModel::append(const QVariantMap& map) {
    return insert(count(), map);
}
//-------------------------------
int ListModel::count() const {
    // qDebug() << "ListModel::count()";
    return m_pDataList->count();
}
//-------------------------------
void ListModel::debug() {
    // qDebug() << "ListModel::debug()";

    Kevin::ListModel& model = *this;

    Kevin::ListItem item;
    // initial
    model.append(item);
    // sample()
    item.sample();
    model.append(item);
    // set value
    item.Title   = "Title 2";
    item.SubType = 3;
    model.append(item);
    // clear
    item.clear();
    model.append(item);

    // cout the list
    int count = model.count();
    for (int i = 0; i < count; i++) {
        qDebug() << i;
        const Kevin::ListItem& item = model.get(i);
        item.dump();
    }
}
//---------------------------------
QVariant ListModel::data(const QModelIndex& index, int role) const {
    // qDebug() << "ListModel::data(" << index << "," << role << ")";

    int row = index.row();
    if (row < 0 || row >= m_pDataList->count()) {
        qDebug() << "ListModel::data(), row =" << row;
        return QVariant();
    }

    const ListItem& data = (*m_pDataList)[ row ];
    switch (role) {
    case TitleRole:
        return data.Title;
    case TypeRole:
        return data.Type;
    case IconSourceRole:
        return data.IconSource;
    case IIDRole:
        return data.IID;
    case SubTypeRole:
        return data.SubType;
    }

    return QVariant();
}
//---------------------------------
int ListModel::insert(int row, const ListItem& data) {
    // qDebug() << "ListModel::insert(" << row << "," << &data << ")";
    if (row < 0)
        row = 0;
    else if (row > m_pDataList->count()) {
        row = m_pDataList->count();
    }

    emit beginInsertRows(QModelIndex(), row, row);
    m_pDataList->insert(row, data);
    emit endInsertRows();
    // emit countChanged(m_data.count());
    return 0;
}
//---------------------------------
int ListModel::insert(int row, const QVariantMap& map) {
    // do not check row. row will be checked in insert()

    // extract data from map
    QVariantMap::const_iterator iter;
    Kevin::ListItem             data;
    iter = map.find("dmTitle");
    if (iter != map.end()) data.Title = iter->toString();

    iter = map.find("dmType");
    if (iter != map.end()) data.Type = iter->toString();

    iter = map.find("dmIID");
    if (iter != map.end()) data.IID = iter->toString();

    iter = map.find("dmIconSource");
    if (iter != map.end()) data.IconSource = iter->toString();

    iter = map.find("dmSubType");
    if (iter != map.end()) data.SubType = iter->toInt();

    return insert(count(), data);
}
//---------------------------------
void ListModel::remove(int row) {
    // qDebug() << "ListModel::remove(" << row << ")";
    if (row < 0 || row >= m_pDataList->count()) {
        return;
    }

    beginRemoveRows(QModelIndex(), row, row);
    m_pDataList->removeAt(row);
    endRemoveRows();
}
//---------------------------------
int ListModel::rowCount(const QModelIndex& parent) const {
    // qDebug() << "ListModel::rowCount(" << parent << ")";
    Q_UNUSED(parent); // do not use parent

    // debug for isValid()
    // qDebug() << "debug : parent.isValid() =" << parent.isValid();
    // parent.isValid() means : parent is OK , row is ok row >=0 and row<count

    //  root node has rows. others none
    if (parent.row() < 0) return m_pDataList->count();
    return 0;
}
//---------------------------------
QHash<int, QByteArray> ListModel::roleNames() const {
    // qDebug() << "ListModel::roleNames()";
    QHash<int, QByteArray> roles;
    // dm : data model
    roles[ TitleRole ]      = "dmTitle";      // 1
    roles[ TypeRole ]       = "dmType";       // 2
    roles[ IIDRole ]        = "dmIID";        // 3
    roles[ IconSourceRole ] = "dmIconSource"; // 4
    roles[ SubTypeRole ]    = "dmSubType";    // 5
    return roles;
}
//---------------------------------
void ListModel::sample() {
    // qDebug() << "ListModel::sample()";
    Kevin::ListItem item;

    // load qml
    item.Title = tr("Load QML");
    item.Type  = "Rect";
    append(item);

    // List View
    item.Title = tr("List View");
    item.Type  = "cModel";
    append(item);
}
//---------------------------------
bool ListModel::setData(const QModelIndex& index, const QVariant& value, int role) {
    // qDebug() << "ListModel::setData(" << index << "," << value << "," << role << ")";
    int row = index.row();
    if (row < 0 || row >= m_pDataList->count()) return false;

    ListItem& data = (*m_pDataList)[ row ];

    switch (role) {
    case TitleRole:
        data.Title = value.toString();
        break;
    case TypeRole:
        data.Type = value.toString();
        break;
    case IconSourceRole:
        data.IconSource = value.toString();
        break;
    case IIDRole:
        data.IID = value.toString();
        break;
    case SubTypeRole:
        data.SubType = value.toInt();
        break;
    default:
        return false;
    }
    QVector<int> roles = {role};

    emit dataChanged(index, index, roles);
    return true;
}
} // namespace Kevin
